const Cache = require('../utils/cache')
const logger = require('../utils/logger')
const Department = require('../models/department')
const { Op } = require('sequelize')

class DepartmentService {
  // 缓存键前缀
  static CACHE_KEY = {
    TREE: 'department:tree',
    CHILDREN: 'department:children:',
    PARENT: 'department:parent:',
    DETAIL: 'department:detail:'
  }

  /**
   * 获取部门树
   */
  static async getDepartmentTree() {
    try {
      // 从数据库获取所有部门
      const departments = await Department.findAll({
        attributes: [
          'id', 'name', 'code', 'parent_id', 'order_num',
          'template_id', 'level', 'status'
        ],
        order: [
          ['parent_id', 'ASC'],
          ['order_num', 'DESC'],
          ['id', 'ASC']
        ]
      })

      // 使用Map优化树构建
      const map = new Map()
      const tree = []

      // 第一次遍历建立映射关系
      departments.forEach(dept => {
        const node = {
          ...dept.toJSON(),
          children: []
        }
        map.set(dept.id, node)
      })

      // 第二次遍历构建树结构
      departments.forEach(dept => {
        const node = map.get(dept.id)
        if (dept.parent_id === null) {
          tree.push(node)
        } else {
          const parent = map.get(dept.parent_id)
          if (parent) {
            parent.children.push(node)
          }
        }
      })

      // 添加hasChildren标志
      const addHasChildren = (nodes) => {
        nodes.forEach(node => {
          node.hasChildren = node.children.length > 0
          if (node.hasChildren) {
            addHasChildren(node.children)
          }
        })
      }

      addHasChildren(tree)
      return tree
    } catch (error) {
      logger.error('获取部门树失败:', error)
      throw error
    }
  }

  /**
   * 创建部门
   */
  static async createDepartment(data) {
    try {
      const department = await Department.create(data)
      await this.clearDepartmentCache(data.parent_id)
      return department
    } catch (error) {
      logger.error('创建部门失败:', error)
      throw error
    }
  }

  /**
   * 更新部门
   */
  static async updateDepartment(id, data) {
    try {
      const department = await Department.findByPk(id)
      if (!department) {
        throw new Error('部门不存在')
      }

      await department.update(data)
      await this.clearDepartmentCache(id)
      return department
    } catch (error) {
      logger.error('更新部门失败:', error)
      throw error
    }
  }

  /**
   * 删除部门
   */
  static async deleteDepartment(id) {
    try {
      const department = await Department.findByPk(id)
      if (!department) {
        throw new Error('部门不存在')
      }

      // 检查是否有子部门
      const hasChildren = await Department.count({
        where: { parent_id: id }
      })
      if (hasChildren > 0) {
        throw new Error('存在子部门，无法删除')
      }

      await department.destroy()
      await this.clearDepartmentCache(id)
      return true
    } catch (error) {
      logger.error('删除部门失败:', error)
      throw error
    }
  }

  /**
   * 更新部门父级
   */
  static async updateParent(departmentId, newParentId) {
    try {
      // 检查是否形成循环
      if (await this.wouldCreateCycle(departmentId, newParentId)) {
        throw new Error('不能将部门移动到其子部门下')
      }

      // 更新数据库
      await Department.update(
        { parent_id: newParentId },
        { where: { id: departmentId } }
      )

      // 清理相关缓存
      await this.clearDepartmentCache(departmentId)
      if (newParentId) {
        await this.clearDepartmentCache(newParentId)
      }

      // 获取并缓存新的树结构
      const departments = await Department.findAll()
      const tree = this.buildTree(departments)
      await Cache.set(this.CACHE_KEY.TREE, tree, 3600)

      return true
    } catch (error) {
      logger.error('更新部门父级失败:', error)
      throw error
    }
  }

  /**
   * 检查是否会形成循环引用
   */
  static async wouldCreateCycle(departmentId, newParentId) {
    if (!newParentId) return false
    
    let currentId = newParentId
    while (currentId) {
      if (currentId === departmentId) return true
      const parent = await Department.findByPk(currentId)
      currentId = parent ? parent.parent_id : null
    }
    return false
  }

  /**
   * 清理部门相关缓存
   */
  static async clearDepartmentCache(departmentId) {
    try {
      // 清理树缓存
      await Cache.del(this.CACHE_KEY.TREE)
      
      // 清理子部门缓存
      await Cache.del(this.CACHE_KEY.CHILDREN + departmentId)
      
      // 清理父部门缓存
      await Cache.del(this.CACHE_KEY.PARENT + departmentId)

      // 清理部门详情缓存
      await Cache.del(this.CACHE_KEY.DETAIL + departmentId)

      // 清理相关的模糊匹配缓存
      await Cache.delByPattern(`${this.CACHE_KEY.CHILDREN}*`)
      await Cache.delByPattern(`${this.CACHE_KEY.PARENT}*`)
    } catch (error) {
      logger.error('清理部门缓存失败:', error)
      throw error
    }
  }

  /**
   * 构建树形结构
   */
  static buildTree(departments, parentId = null) {
    const tree = []
    departments
      .filter(dept => dept.parent_id === parentId)
      .forEach(dept => {
        const node = {
          ...dept.toJSON(),
          children: this.buildTree(departments, dept.id)
        }
        tree.push(node)
      })
    return tree
  }

  /**
   * 搜索部门
   */
  static async searchDepartments(keyword) {
    try {
      const departments = await Department.findAll({
        where: {
          name: {
            [Op.like]: `%${keyword}%`
          }
        }
      })
      return departments
    } catch (error) {
      logger.error('搜索部门失败:', error)
      throw error
    }
  }
}

module.exports = DepartmentService 